#pragma once

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <fstream>
#include <unordered_map>
#include "Comm.hpp"
#include "Log.hpp"

using namespace std;
using namespace LogModule;
const std::string sep = "\r\n";
const string LineSep = " ";
const string HeaderLineSep = ": ";
const std::string BlankLine = sep;
const std::string gdefaulthomepage = "wwwroot";
const std::string http_version = "HTTP/1.0";
const std::string page404 = "wwwroot/404.html";
const std::string firstpage = "index.html";

bool ParseOneLine(string &str, string *out, const string &sep)
{
    auto pos = str.find(sep);
    if (pos == string::npos)
        return false;
    *out = str.substr(0, pos);
    str.erase(0, pos + sep.size());

    return true;
}
//header:  key: value
bool SplitString(const string& header, const string& sep, string* key, string* value)
{
    auto pos = header.find(sep);
    if(pos == string::npos) return false;

    *key = header.substr(0, pos);
    *value = header.substr(pos+sep.size());

    return true;
}
// BS模式
class HttpRequest
{
    void ParseReqLine(string& _req_line,const string LineSep)
    {
        stringstream ss(_req_line);
        ss>>_method>>_uri>>_version;

        //_uri = gdefaulthomepage + _uri;
    }
    bool ParseHeaderkv()
    {
        string key, value;
        for(auto& header: _req_header)
        {
            if(SplitString(header, HeaderLineSep, &key, &value))
            {
                _headerkv.insert(make_pair(key, value));
            }
        }
        return true;
    }
    bool ParseHeader(string& request_str)
    {
        string line;
        while(1)
        {
            bool r = ParseOneLine(request_str, &line, sep);
            if(r&&!line.empty())
            {
                _req_header.push_back(line);
            }
            else if(r && line.empty())
            {
                _blank_line = sep;
                break;
            }
            else return false;


        }
        ParseHeaderkv();
        return true;
    }
public:
    HttpRequest()
    {
    }
    bool IsHasArgs()
    {
        return 1;
    }
    void Deserialize(string &request_str)
    {
        if (ParseOneLine(request_str, &_req_line, sep)){
            // 提取请求行的详细字段
            ParseReqLine(_req_line, LineSep);
            ParseHeader(request_str);
            _body = request_str;

            //分析请求中， 是否含有参数
            if(_method == "POST")
            {
                _isexec = true;
                _args = _body;
                _path = _uri;
            }
            else if(_method == "GET")
            {
                auto pos = _uri.find('?');
                if(pos != string::npos){
                    //有问号->body有参数
                    _isexec = true;
                    // /login?name=zhangsan&password=12345
                    _path = _uri.substr(0, pos); // /login
                    _args = _uri.substr(pos+1);
                }
            }
        } 
       
    }
    void Print()
    {
        std::cout <<"_method: "<<_method<<std::endl;
        std::cout <<"_uri: "<<_uri<<std::endl;
        std::cout <<"_version: "<<_version<<std::endl;

        for(auto& kv:_headerkv)
        {
            cout<<kv.first<<": "<<kv.second<<endl;
        }
        std::cout <<"_blank_line: "<<_blank_line<<std::endl;

        std::cout <<"_body: "<<_body<<std::endl;

    }
    string URI()
    {
        return _uri;
    }
    void SetUri(const std::string newuri)
    {
        _uri = newuri;
    }
    string GetGontent(const std::string path)
    {
        std::string content;
        std::ifstream in(path, std::ios::binary);
        if(!in.is_open())   return string();
        in.seekg(0,in.end);
        int filesize = in.tellg();
        in.seekg(0, in.beg);

        content.resize(filesize);
        in.read(&content[0], filesize);
        
        in.close();
        return content;
        // std::string content;
        // ifstream in(_uri);
        // if(!in.is_open())   return string();

        // string line;
        // while(getline(in, line))
        // {
        //     content += line;
        // }
        // in.close();
        // return content;
    }
    string GetArgs()
    {
        return _args;
    }
    string GetPath()
    {
        return _path;
    }
    string Suffix()
    {
        auto pos = _uri.rfind(".");
        if(pos == string::npos) return string(".html");
        else    return _uri.substr(pos);
    }
    ~HttpRequest()
    {
    }

private:
    string _req_line;
    vector<string> _req_header;
    string _blank_line;
    string _body;   //可能含有参数

    //反序列化过程中，细化我们解析出来的字段
    string _method;
    string _uri;    //用户想要的东西
    string _version;
    string _path;
    string _args;
    unordered_map<string, string> _headerkv;
    bool _isexec = false; 
};

class HttpResponce
{
public:
    HttpResponce():_version(http_version), _blank_line(sep)
    {
    }
    ~HttpResponce()
    {
    }

    void Build(HttpRequest& req)
    {   
        std::string uri = gdefaulthomepage + req.URI();
        if(uri.back() == '/')
        {
            uri += firstpage;
            //req.SetUri(uri);
        }

        _content = req.GetGontent(uri);
        Code2Desc();
        req.Print();
        if(_content.empty())
        {
            //用户请求资源不存在
            _status_code = 404;
            //req.SetUri(page404);
            _content = req.GetGontent(uri);
        }
        else
        {
            _status_code = 200;
        }
        _status_desc = _code_desc_map[_status_code]; // 和状态码强相关
        if(!_content.empty())
        {
            SetHeader("Content-Length", std::to_string(_content.size()));
        }
        LOG(LogLevel::DEBUG) << "客户端在请求："<<req.URI();

        string mine_type = Suffix2Desc(req.Suffix());
        SetHeader("Content-Type", mine_type);
        for(auto& header: _header_kv)
        {
            _resp_header.push_back(header.first + HeaderLineSep + header.second + sep);
        }
        _body = _content;

    }
    void Serialize(std::string* resp_str)
    {
        _resp_line = _version + LineSep + std::to_string(_status_code) + LineSep + _status_desc + sep;

        //序列化
        *resp_str = _resp_line;
        for(auto& line: _resp_header)
        {
            *resp_str += (line + sep);
        }
        *resp_str += _blank_line;
        *resp_str += _body;
    }
    void SetHeader(const string& k, const string& v)
    {
        _header_kv[k] = v;
    }
    void SetCode(int code)
    {
        _status_code = code;
        _status_desc = _code_desc_map[_status_code];
    }
    void SetBody(const string& body)
    {
        _body = body;
    }
private:
    void Code2Desc()
    {
        // Todo
        _code_desc_map[200] = "OK";
        _code_desc_map[404] = "Not Found";
        _code_desc_map[301] = "Moved Permanently";
        _code_desc_map[302] = "Found";
    }
    string Suffix2Desc(const std::string& suffix)
    {
        if(suffix == ".html")   return "text/html";
        else if(suffix == ".jpg")   return "application/x-jpg";
        else return "text/html";
    }
private:
    //必备的要素
    string _version;
    int _status_code;
    string _status_desc;
    unordered_map<int, std::string> _code_desc_map; //状态码转换表
    string _content;
    unordered_map<string, string> _header_kv;

    std::string _resp_line;
    std::vector<string> _resp_header;
    std::string _blank_line;
    std::string _body;

};

